# -*- coding: utf-8 -*-

import json
import logging
from urlparse import urlparse, urljoin
from bisect import bisect_left

from django.conf import settings

from api.preset.model import Lottery
from common.cache import redis_cache
from common.cache.redis_cache import get_allow_game_channels
from common.lottery import LOTTERY_TYPE, GAME_TYPE, METIS_GAME_TYPE
from common.lottery.cyclical.abstract.activity import get_base_reward
from common.lottery.cyclical.model import ACTIVITY_LOGIC
from common.pay.model import PAY_TYPE
from common.preset.db import lottery as lottery_db
from common.preset.db import parts as parts_db
from common.preset.db import reward as reward_db
from common.preset.db import tab as tab_db
from common.preset.db.preset import get_preset
from common.preset.model.preset import DEVICE_TYPE, PRESET_PARTS_TABLE
from common.platform.common.model import PLATFORM_TYPE
from common.stats import MG_BIGBANG_COLL
from common.stats.account import get_account_aggr
from common.utils.decorator import local_memory_cache
from common.utils.exceptions import ResourceNotModified, ResourceNotFound
from common.utils.limit import check_abtest
from common.utils.tz import now_ts

_LOGGER = logging.getLogger(__name__)


@local_memory_cache('activity_type', 600)
def get_reward_activity_types():
    '''
    获取现在所有正在加奖的彩种
    '''
    activity_types = []
    rewards = reward_db.list_reward({})[0]
    for reward in rewards:
        activity_type = reward.activity_type
        cond = json.loads(reward.condition)
        logic = ACTIVITY_LOGIC[activity_type]
        start_ts = logic.calc_start_ts_by_term(cond['term'][0][0])
        end_ts = logic.calc_start_ts_by_term(cond['term'][0][1]) + 600
        if start_ts <= now_ts() <= end_ts:
            activity_types.append(activity_type)
    return activity_types


def _chn2type(chn):
    if chn and chn.startswith('ios'):
        return DEVICE_TYPE.IOS
    else:
        return DEVICE_TYPE.ANDROID


def _get_preset(app_version, device_type, chn=None, ip=None):
    preset = get_preset(
        app_version=app_version, device_type=device_type, chn=chn)
    if not preset:
        raise ResourceNotFound()
    data = {} if not preset.content else json.loads(preset.content)
    data['id'] = preset.id
    data['last_modified'] = preset.last_modified
    return data


def _calc_reward(activity_type, bet_type, rate, amount):
    resp = {}
    reward = get_base_reward(activity_type, bet_type)
    if isinstance(reward, (list, tuple)):
        if len(reward) == 1:
            reward = float(reward[0])
        else:
            resp['amount'] = []
            for r in reward:
                resp['amount'].append(
                    round(float(float(r) * (rate / 100.0) + amount), 3))
    else:
        reward = float(reward)
    if not resp:
        resp['amount'] = round(float(reward * (rate / 100.0) + amount), 3)

    return resp


def view_reward_config(params):
    cached = redis_cache.get_reward_config(
        params['activity_type'], params['term'], params['bet_type'])
    if cached:
        return _calc_reward(params['activity_type'], params['bet_type'],
                            float(cached['rate']), float(cached['amount']))

    rate, amount = reward_db.get_reward_config(
        params['activity_type'], params['term'], params['bet_type'])

    v = {'rate': rate, 'amount': amount}
    redis_cache.set_reward_config(
        params['activity_type'], params['term'], params['bet_type'], v)
    return _calc_reward(params['activity_type'], params['bet_type'],
                        v['rate'], v['amount'])


def view_preset(app_version, chn, last_modified, user_id):
    device_type = _chn2type(chn)
    data = _get_preset(app_version, device_type, chn)
    if last_modified >= data['last_modified']:
        raise ResourceNotModified()
    for k in ('recommend', 'banner'):
        data.pop(k, None)

    return data


def view_pay_type(app_version, chn):
    device_type = _chn2type(chn)
    data = _get_preset(app_version, device_type, chn)
    item_ids = data.get('pay', [])
    resp = []
    for item_id in item_ids:
        table = PRESET_PARTS_TABLE['pay']
        item = parts_db.get(table, item_id)
        if not item or item.status != 0:
            continue
        item = item.as_dict()
        data = {
            'name': item['title'],
            'pay_type': item['pay_type'],
            'icon': item['icon'],
            'comment': item['desc_short'],
            'min_amount': item['least_pay'],
            'highlight': item['highlight'],
            'category': item['category'],
        }
        if item['pay_type'] in [PAY_TYPE.UNIONAGENCY_V2_ALI, PAY_TYPE.UNIONAGENCY_V2_BANKCARD,
                                PAY_TYPE.UNIONAGENCY_V2_WX]:
            if int(app_version) < 24:
                data['open_url'] = settings.UNIONAGENCY_GATEWAY_URL_V2 + '?pay_type=%s' % item['pay_type']
        if item['pay_type'] in (PAY_TYPE.JUSTPAY_ALI_QUOTA,):
            my_expect_list = [200, 500, 1000, 2000, 5000, 10000]
            data['quotas'] = get_closest_quotas(my_expect_list)
        elif item['pay_type'] in (PAY_TYPE.JUSTPAY_WX_QUOTA,):
            data['quotas'] = redis_cache.get_wx_quotas()
        resp.append(data)
    return resp


def get_closest_quotas(my_expect_list):
    final_list = []
    quotas = redis_cache.get_alipay_quotas()
    quotas = list(map(lambda x: float(x), quotas))
    quotas = sorted(quotas, key=lambda x: float(x))
    if len(my_expect_list) >= len(quotas):
        _LOGGER.info("len(my_expect_list) >= len(quotas)")
        return quotas
    for my_expect in my_expect_list:
        num = take_closest(quotas, my_expect)
        final_list.append(num)
        quotas.remove(num)

    return final_list


def take_closest(target_list, expect_number):
    """
    Assumes myList is sorted. Returns closest value to myNumber.

    If two numbers are equally close, return the smallest number.
    """
    pos = bisect_left(target_list, expect_number)
    if pos == 0:
        return target_list[0]
    if pos == len(target_list):
        return target_list[-1]
    before = target_list[pos - 1]
    after = target_list[pos]
    if after - expect_number < expect_number - before:
        return after
    else:
        return before


def view_single_part(part_name, app_version, chn):
    """有些预置数据是全局的，直接写在preset表里"""
    device_type = _chn2type(chn)
    data = _get_preset(app_version, device_type, chn)
    data = data.get(part_name, {})
    return data


def view_parts(part_name, app_version, chn, user_id, model=None):
    """ model是api.BaseModel子类，用来生成输出
    """
    device_type = _chn2type(chn)
    data = _get_preset(app_version, device_type, chn=chn)
    data.pop('last_modified')
    item_ids = data.get('pages' if part_name == 'loading' else part_name, [])
    resp = []
    ts = now_ts()
    for item_id in item_ids:
        table = PRESET_PARTS_TABLE[part_name]
        item = parts_db.get(table, item_id)
        if not item:
            _LOGGER.error('%s id %s not exist', part_name, item_id)
            continue
        if part_name != 'shortcut':
            if ts < item.start_ts or ts > item.end_ts:
                continue
        item = item.as_dict()
        if not check_abtest(user_id, chn, app_version, item):
            continue
        resp.append(model(item) if model is not None else item)
    return resp


def can_show_game(user_id, chn):
    allowed_channels = get_allow_game_channels()
    if chn not in allowed_channels:
        return False
    user_stats = MG_BIGBANG_COLL.user_stats.find_one({'_id': user_id}) or {}
    account__aggr = get_account_aggr(user_id)
    recharge_amount = user_stats.get('recharge', {}).get('total', 0)
    active_days = account__aggr.get('active_days', 0)
    buy_count = user_stats.get('pay', {}).get('count', 0)
    if recharge_amount > 50 and active_days > 2 and buy_count > 10:
        return True
    return False


def is_senior_user(user_id):
    if not user_id:
        return False

    user_stats = MG_BIGBANG_COLL.user_stats.find_one({'_id': user_id}) or {}
    recharge_amount = user_stats.get('recharge', {}).get('total', 0)
    recharge_count = user_stats.get('recharge', {}).get('count', 0)

    if recharge_amount >= 50 and recharge_count >= 2:
        return True

    return False


def get_available_lottery_preset(p_param, user_id=None):
    chn = p_param.get('chn')
    cvc = p_param.get('cvc')

    senior_user = is_senior_user(user_id)

    device_type = _chn2type(chn)
    _list = []
    lottery_priority = {}
    preset = _get_preset(cvc, device_type, chn)
    game_off = preset['ipay'].get('off_status')
    for each in lottery_db.get_all_avaliable_lottery():
        if user_id and each.type > 100 and can_show_game(user_id, chn):
            lottery_priority[each.type] = each.priority
            _list.append(each)
        if not (each.min_cvc <= cvc <= each.max_cvc):
            continue
        if not device_type & each.device_type:
            continue
        if each.pass_chn and ',%s,' % chn not in each.pass_chn:
            continue
        if ',%s,' % chn in each.exclude_chn:
            continue
        if game_off and not senior_user and each.type > 100:
            continue
        if each.type not in lottery_priority or each.priority > lottery_priority[each.type]:
            lottery_priority[each.type] = each.priority
            _list.append(each)
    _list = filter(lambda x: x.priority >= lottery_priority[x.type], _list)
    _list.sort(key=lambda x: x.sort_id)
    return _list


def get_all_tab():
    tab_list = tab_db.get_all_avaliable_tab()
    return sorted(tab_list, key=lambda x: x.sort_id)


def create_lottery_lites(lottery_lists):
    lottery_lites = []
    for lottery in lottery_lists:
        lottery_lite = Lottery()
        lottery_lite['id'] = lottery.sort_id
        lottery_lite['image'] = get_fixed_bucket(lottery.image)
        lottery_lite['cmd'] = lottery.cmd
        lottery_lite['tab'] = lottery.tab
        lottery_lite['type'] = lottery.type
        lottery_lite['platform'] = PLATFORM_TYPE.get_label(lottery.platform)
        if lottery.platform == PLATFORM_TYPE.WITCH:
            lottery_lite['title'] = LOTTERY_TYPE.get_label(lottery.type) \
                                    or GAME_TYPE.get_label(lottery.type)
        elif lottery.platform == PLATFORM_TYPE.METIS:
            lottery_lite['title'] = METIS_GAME_TYPE.get_label(lottery.type)
        lottery_lite['play_id'] = lottery.type
        lottery_lite['desc'] = lottery.desc
        lottery_lite['bet_type'] = lottery.bet_type
        lottery_lite['is_vertical'] = lottery.is_vertical
        lottery_lite['is_new_game'] = lottery.is_new_game
        lottery_lite['is_hot_game'] = lottery.is_hot_game
        lottery_lites.append(lottery_lite)
    return lottery_lites


def fill_amount(lottery_type, _list, term, rate_config):
    for each in _list:
        bet_id = each['play_id']
        params = {'activity_type': lottery_type, 'bet_type': bet_id, 'term': term}
        result = view_reward_config(params)

        amounts = rate_config.get(bet_id, 0)
        reward = result['amount']

        if isinstance(amounts, (list, tuple)):
            amounts = ",".join(str(i) for i in amounts)
        if isinstance(reward, (list, tuple)):
            reward = ",".join(str(i) for i in reward)

        each.update({'amounts': amounts, "reward": reward})


def get_fixed_bucket(bucket_url, bucket='default', disable_domain=False):
    if not bucket_url:
        return None
    parse_res = urlparse(bucket_url)
    if disable_domain:
        url = parse_res.path
    else:
        url = urljoin(settings.QINIU_BUCKETS[bucket], parse_res.path)

    return url
